iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 3
1
自我挑戰組

Golang魔法使 ─ 30天從零開始學習Go語言 | 比Python還簡單 | 理科生一定學得會 | 文科生不好說系列 第 3

#3 字串 ─ 知世:反正我們是屬於正義的一方 | Golang魔法使

  • 分享至 

  • xImage
  •  

前言

這次小櫻前往水族館校外教學,卻不幸遇到可惡的「字串」Golang牌,導致水族館員和企鵝差點被淹死,小櫻的哥哥恰好在這裡打工,縱身一躍跳進水池解救了大家,像這樣

要如何把這個囂張的Golang牌繩之以法呢?

了解字串前要先了解什麼是字元

在了解字串前我們必需先了解什麼是字元,字元其實就是指「單一一個字」,這個字也是由數字所組成,在Golang中是以 utf8 來做為字元的轉法,舉個例子,小櫻的「小」在是以 23567 的二進位來儲存「櫻」則是以 27387 的二進位來儲存

我們在更細的來說,為什麼要有型態,有型態主要是為了方便魔法使做事,不然沒有型態的情況下,根本不知道是要用「小」還是要用 23567,因為這兩個在魔仗中都長的一樣。

要宣告一個字元我們會用 rune (中文:符文)來表示,rune 其實就是 int32 的代稱,只是因為 rune 聽起來更接近字元所代表的「意義」,這件事在魔法牌中非常重要,越是能貼近魔法使使用上的直覺越好

package main
import "fmt"
func main(){
    var a rune = '小' // 以單引號包住字元
    var b rune = '櫻'
    fmt.Println(a)
    fmt.Println(b)
}

執行結果:
23567
27387

為什麼會這樣?

因為 rune 就是 int32,通過 fmt.Println 當然會把他當作數字來做處理,如果我們要印「文字」出來,則必需使用 fmt.Printfprintf 指的就是 print + formatformat (中文:格式)決定要以什麼形式印出,使用方法如下:

package main
import "fmt"
func main(){
    var a rune = '小'
    var b rune = '櫻'
    fmt.Printf("%c", a)
    fmt.Printf("%c", b)
}

其中的 %c 就是告訴魔仗我要印字元出來,至於要印哪個字元呢?則是看 , 後面第一個變數

執行結果:
小櫻

當然也可以用 %c %c 他會依序對應 , 後面的變數

package main
import "fmt"
func main(){
    var a rune = '小'
    var b rune = '櫻'
    fmt.Printf("%c%c", a, b)
}

執行結果:
小櫻

另外常用的還有 %d, %f, %s

%c 的 c 是指 character 以字元印出

%d 的 d 是指 decimal 以十進位印出

%e 的 e 是指 exponent 以科學計號方式印出

%f 的 f 是指 float 以浮點數印出

%s 的 s 是指 string 以字串印出

%% 是用來印出 % 不然 Printf 會有 bug

Printf 不神奇,單引號才是

初學者可能一時之間覺得頭有點痛,好像了解但其實又不是很懂,這麼說好了,其實當我們在Golang牌上刻上 '小' 這個字時,魔仗會直接把他變成 23567 你甚至可以試試把 '小' 減去 23566 讓他變成 1

package main
import "fmt"
func main(){
    var a rune = '小' - 23566
    fmt.Printf("%d", a)
}

執行結果:
1

'小' - 23566 在魔仗的中會直接視為 23567-23566rune 則是會視為 int32

fmt.Printf("%d", a) 則是視為 fmt.Printf("%d", 1)

這種「視為」的情況太多了,所以我們要多利用這種方法來學習,才能收服差點把企鵝淹死的Golang牌

Print 不神奇,Printf 才是

剛剛教了大家怎麼一眼看穿單引號,現在要教大家一眼看穿 Print,其實 Print 在做的事,就是用預設的型式來做印出,什麼是預設的型式?比如整數類型就以%d來印,浮點數就以%g來印(%e for large exponents, %f otherwise.),在 Golang 中,這個預設類型可以直接用 %v 來表示

package main
import "fmt"
func main(){
    a := 10
    fmt.Printf("%d", a)
    fmt.Printf("%v", a)
    fmt.Print(a)
}

執行結果:
101010

Print(a) 可以視為 Printf("%v", a) 又因為 a 的型態是 int 所以 %v 就是 %d 因此就是 Printf("%d", a)

Println 不神奇只是多了個換行 \n

在程式語言中,有一些字元沒辦法那麼容易表示,比如換行,因此可以用 \n 來表示

func main(){
    a := 10
    fmt.Printf("%d\n", a)
    fmt.Printf("%v\n", a)
    fmt.Println(a)
}

執行結果:
10
10
10

字串是什麼?

相信大家都知道字元是什麼了,「字元不過就是一串數字」,那「字串」呢?字串其實就是一串「字元」,這次教學只會點到這裡就停了,因為現在教的還不夠還沒辦法完美解釋。

就像小櫻只知道他哥很常打工,並且常常遇到他哥,但他根本不知道他哥是照著他的行程在打工,小櫻去水族館他哥就在水族館打工,去溜冰場他哥就在溜冰場打工,去採草莓他哥就去草莓園打工,(邦友可以留一下集數我忘了)

所以各位魔法使只要先知道怎麼用就好了,想了解原理,可以去學看「C魔法使」,但聽起來好爛,還是要出「Clang魔法使」、「科學超C語言」、「玩偶遊C」、「我們仍未知道那天所寫的C的意思」、「C利人妻」

package main
import "fmt"
func main(){
    var release string = "封印解除"
    release2 := "レリーズ"
    fmt.Println(release)
    fmt.Println(release2)
}

執行結果:
封印解除
レリーズ

舉個例子大家應該就懂了

字元的運算剛剛被我解惑了一下大家應該都懂了,就跟整數是一樣的,那麼字串呢?字串在用的只有「加法」啦,這個在魔法科學中常稱為 concatenate

package main
import "fmt"
func main(){
    str1 := "隱藏著黑暗力量的鑰匙啊"
    str2 := "在我面前顯示你真正的力量"
    fmt.Println(str1 + str2)
}

執行結果:
隱藏著黑暗力量的鑰匙啊在我面前顯示你真正的力量

就是這麼簡潔有力!如果換做是C魔法牌,你必需再額外使用 string.h 並呼叫 strcat() 但是C魔法牌的彈性仍是有他的好處

另外提一個有趣的現象,大家有想過要怎麼把數字轉成字串一起填入嗎?

很好報錯了!因為 4 不是字串不能直接加,這是一個優勢但稍微麻煩是劣勢

圖源:https://www.youtube.com/watch?v=YFuqbgDqib4

這是一個不錯的設計,在某些卡牌中,比如 javascript,在進行加法時,有時會誤把數字相加當作字串相加,因為魔法使並不好知道這個變數是數字還是字串,javascript自己知道但他不說。而同為弱型態的php則是巧妙地避開這問題,php 字串相加用. 數字相加用 +。而pythongolang一樣把數字和字串相加時會報錯。文末會繼續補充

在 Golang 中
字串 + 字串 Ok
數字 + 數字 Ok
字串 + 數字 噴錯

那麼不然我們把數字轉成字串好了?

數字轉成字串?

首先如果只是要印出的話可以用 Printf 來印出

法一:Printf

package main
import "fmt"
func main(){
    sakura := "小櫻今年"
    grade := "年級"
    fmt.Printf("%s%d%s", sakura, 4, grade)
}

執行結果:
小櫻今年4年級

法二:Print

package main
import "fmt"
func main(){
    sakura := "小櫻今年"
    grade := "年級"
    fmt.Print(sakura, 4, grade)
}

執行結果:
小櫻今年 4 年級

這方法先前沒教

fmt.Print(sakura, 4, grade)

可以直接視為

fmt.Print(sakura)
fmt.Print(" ")
fmt.Print(4)
fmt.Print(" ")
fmt.Print(grade)

但印出來中間會多一個空白,跟 python 中的printjavascript 中的 console.log()

以上提到的方法都是直接印在螢幕上(標準輸出 standard output),有沒有方法是直接印在變數裡

使用 fmt.Sprintf()

法三:法一、法二都垃圾要用就用 Sprintf

package main
import "fmt"
func main(){
    sakura := "小櫻今年"
    grade := "年級"
    result := fmt.Sprintf("%s%d%s", sakura, 4, grade)
    fmt.Printf(result)
}

這個用法跟 C 很類似但稍有不同,文末討論

字串轉成數字?

如果今天我是想把 "4" 轉成 4 那要怎麼轉呢?
其實這個可以把字串拆成字元再用字元去做運算,但是剛剛就說了,依現在各位魔法使的實力,還不夠,所以我們就先跳過吧!

深入討論

建議新手這裡可以跳過

C 語言

剛剛說了 golang 在字串加數字的一些邏輯,我們來看一下其他語言

在 C 語言中我們可以用一樣sprintf的方法來做,要注意的事第一個參數放的事有足夠大小的字串指標

sprintf() 如果成功,則返回寫入的字符的總數,不包括\0,否則在發生故障的情況下,返回一個負數。

#include<stdio.h>
int main(){
    char sakura[64] = "小櫻今年";
    char* grade = "年級";
    sprintf(sakura, "%s%d%s", sakura, 4, grade);
    printf(sakura);
    return 0;
}

javascript

javascript 中我們可以把字串直接與數字相加,在進行字串與數字相加時 javascirpt 會直接把數字做為字串處理

var sakura = "小櫻今年";
var grade = "年級";
var result = sakura + 4 + grade;
console.log(result);

php

php 中字串相加用 . 數字用 + ,缺點是物件導向時只能用 -> 不能用 . 但 php 一開始設計時就不是要走物件導向所以一開始問題不大,現在要用物件才發現有夠麻煩 . 要打 ->

另一種方法是把變數鑲進雙引號裡面,這感覺跟 dart 和新版的 javascript 有點類似

<?php
    $sakura = "小櫻今年";
    $grade = "年級";
    $result = $sakura.(4).$grade;
    echo $result;
    
    $result = "{$sakura}4{$grade}";
    echo $result;
?>

java, python

java 中就好玩了,雖然大家都覺得java 是強型態,python 是弱型態,但是 java 卻能支援字串加數字,因為 java 在做相加時會自動將 4 轉成字串

public class Strcat{
    public static void main(String[] args){
        String sakura = "小櫻今年";
        String grade = "年級";
        String result = sakura + 4 + grade;
        System.out.println(result);
    }
}
sakura = "小櫻今年"
grade = "年級"
# print(sakura + 4 + grade) 報錯
print(sakura + str(4) + grade)

dart

dart 在數字加字串時習慣會直接像用 php 的那種方法將變數鑲進去

void main(){
    var sakura = "小櫻今年";
    var grade = "年級";
    var number = 4;
    print(sakura + number.toString() + grade);
    print("$sakura$number$grade");
}

rust

在 rust 中則是類似用 sprintf() 的做法來實現

fn main(){
    let sakura = "小櫻今年";
    let grade = "年級";
    let result = format!("{}{}{}", sakura, 4, grade);
    print!("{}", result);
}

rust 中的 string 挺複雜的,話說今年 2020 還沒看到鐡人賽有人教 rust 如果有可以留個言


圖片大多來自:庫洛魔法使第一季第三集以及庫洛魔法使第一季第四集


上一篇
#2 零與壹的魔法世界 ── 宣告數字型態的變數 | Golang魔法使
下一篇
#4 布林變數與 if-else, switch-case 流程控制 | Golang魔法使
系列文
Golang魔法使 ─ 30天從零開始學習Go語言 | 比Python還簡單 | 理科生一定學得會 | 文科生不好說30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言